#pragma once
#include "util.hpp"
#include <mutex>
#
class user_table
{
private:
    MYSQL *_mysql;
    std::mutex _mutex;

public:
    user_table(const std::string &host,const std::string &username,const std::string &passwd,const std::string &dbname,int16_t port = 3306)
    {
        _mysql = mysql_util::mysql_create(host, username, passwd, dbname, port);
        assert(_mysql);
    }
    ~user_table()
    {
        mysql_util::mysql_destory(_mysql);
    }
    bool insert(Json::Value &user)
    {
        #define USER_INSERT "insert into user values(null,'%s','%s',1000,0,0);"
        if(user["username"].asCString()==nullptr||user["password"].asCString()==nullptr)
        {
            DLOG("username or password cannot be empty");
            return false;
        }
        char sql[4096];
        sprintf(sql, USER_INSERT, user["username"].asCString(), user["password"].asCString());
        bool ret = mysql_util::mysql_exec(_mysql, sql);
        if (ret == false)
        {
            DLOG("user information insertion failed!!");
            return false;
        }
        return true;
    }
    bool login(Json::Value &user)
    {
        #define USER_LOGIN "select id,score,total_count,win_count from user where username='%s' and password='%s'"
        char sql[4096];
        sprintf(sql, USER_LOGIN, user["username"].asCString(), user["password"].asCString());
        MYSQL_RES* res=nullptr;
        {
            std::unique_lock<std::mutex> lm(_mutex);
            bool ret = mysql_util::mysql_exec(_mysql, sql);
            if (ret == false)
            {
                DLOG("user information insertion failed!!");
                return false;
            }
            res=mysql_store_result(_mysql);
            if(res==nullptr)
            {
                DLOG("no logged in user information");
                return false;
            }
        }
        int row_num=mysql_num_rows(res);
        if(row_num!=1)
        {
            DLOG("the user information queried is not unique!!");
            return false;
        }
        MYSQL_ROW row=mysql_fetch_row(res);
        user["id"]=std::stol(row[0]);
        user["score"]=std::stol(row[1]);
        user["total_count"]=std::stol(row[2]);
        user["win_count"]=std::stol(row[3]);
        return true;
    }
    bool select_by_name(const std::string& name,Json::Value& user)
    {
        #define USER_SELECT_BY_NAME "select id,score,total_count,win_count from user where username='%s'"
        char sql[4096];
        sprintf(sql,USER_SELECT_BY_NAME, name.c_str());
        MYSQL_RES* res=nullptr;
        {
            std::unique_lock<std::mutex> lm(_mutex);
            bool ret = mysql_util::mysql_exec(_mysql, sql);
            if (ret == false)
            {
                DLOG("get user by name failed!!");
                return false;
            }
            res=mysql_store_result(_mysql);
            if(res==nullptr)
            {
                DLOG("have no user info!!");
                return false;
            }
        }
        int row_num=mysql_num_rows(res);
        if(row_num!=1)
        {
            DLOG("the user information queried is not unique!!");
            return false;
        }
        MYSQL_ROW row=mysql_fetch_row(res);
        user["id"]=std::stol(row[0]);
        user["score"]=std::stol(row[1]);
        user["total_count"]=std::stol(row[2]);
        user["win_count"]=std::stol(row[3]);
        return true;
    }
    bool select_by_id(uint64_t id,Json::Value& user)
    {
        #define USER_SELECT_BY_ID "select score,total_count,win_count from user where id=%ld;"
        char sql[4096];
        sprintf(sql, USER_SELECT_BY_ID, id);
        MYSQL_RES* res=nullptr;
        {
            std::unique_lock<std::mutex> lm(_mutex);
            bool ret = mysql_util::mysql_exec(_mysql, sql);
            if (ret == false)
            {
                DLOG("get user by id failed!!");
                return false;
            }
            res=mysql_store_result(_mysql);
            if(res==nullptr)
            {
                DLOG("have no user info!!");
                return false;
            }
        }
         int row_num=mysql_num_rows(res);
        if(row_num!=1)
        {
            DLOG("the user information queried is not unique!!");
            return false;
        }
        MYSQL_ROW row=mysql_fetch_row(res);
        user["score"]=std::stol(row[0]);
        user["total_count"]=std::stol(row[1]);
        user["win_count"]=std::stol(row[2]);
        return true;
    }
    bool win(uint64_t id)
    {
        #define USER_WIN "update user set score=score+30,total_count=total_count+1,win_count=win_count+1 where id=%ld"
        char sql[4096];
        sprintf(sql, USER_WIN, id);
        bool ret = mysql_util::mysql_exec(_mysql, sql);
        if (ret == false)
        {
            DLOG("update win user information failed!!!");
            return false;
        }
        return true;
    }
    bool lose(uint64_t id)
    {
        #define USER_LOSE "update user set score=score-30,total_count=total_count+1 where id=%ld;"
        char sql[4096];
        sprintf(sql, USER_LOSE, id);
        bool ret = mysql_util::mysql_exec(_mysql, sql);
        if (ret == false)
        {
            DLOG("update lose user information failed!!!");
            return false;
        }
        return true;
    }
};